package ruleengine

import (
	"strconv"
	"strings"
)

// 解析器

type Parser struct {
	Tokens   []string
	Position int
}

func NewParser(expression string) *Parser {
	return &Parser{
		Tokens:   strings.Fields(expression), //简单分词（实际项目应使用更复杂的分词器）
		Position: 0,
	}
}

func (p *Parser) Parse() Expression {
	return p.parseExpression()
}

func (p *Parser) parseExpression() Expression {
	return p.parseConditional()
}

func (p *Parser) parseConditional() Expression {
	expr := p.parseLogicalOr()

	if p.match("?") {
		trueBranch := p.parseExpression()
		if !p.match(":") {
			panic("条件表达式缺少':'")
		}
		falseBranch := p.parseExpression()
		return NewConditionalExpression(expr, trueBranch, falseBranch)
	}

	return expr
}

func (p *Parser) parseLogicalOr() Expression {
	expr := p.parseLogicalAnd()

	for p.match("||") {
		right := p.parseLogicalAnd()
		expr = NewBinaryOperationExpression(expr, right, "||")
	}

	return expr
}

func (p *Parser) parseLogicalAnd() Expression {
	expr := p.parseEquality()

	for p.match("&&") {
		right := p.parseEquality()
		expr = NewBinaryOperationExpression(expr, right, "&&")
	}

	return expr
}

func (p *Parser) parseEquality() Expression {
	expr := p.parseComparison()

	for p.match("==", "!=") {
		operator := p.previous()
		right := p.parseComparison()
		expr = NewBinaryOperationExpression(expr, right, operator)
	}

	return expr
}

func (p *Parser) parseComparison() Expression {
	expr := p.parseTerm()

	for p.match(">", ">=", "<", "<=") {
		operator := p.previous()
		right := p.parseTerm()
		expr = NewBinaryOperationExpression(expr, right, operator)
	}

	return expr
}

func (p *Parser) parseTerm() Expression {
	expr := p.parseFactor()

	for p.match("+", "-") {
		operator := p.previous()
		right := p.parseFactor()
		expr = NewBinaryOperationExpression(expr, right, operator)
	}

	return expr
}

func (p *Parser) parseFactor() Expression {
	expr := p.parseUnary()

	for p.match("*", "/") {
		operator := p.previous()
		right := p.parseUnary()
		expr = NewBinaryOperationExpression(expr, right, operator)
	}

	return expr
}

func (p *Parser) parseUnary() Expression {
	if p.match("!") {
		right := p.parseUnary()
		// 实现逻辑非操作
		return NewFunctionCallExpression("not", []Expression{right})
	}

	return p.parsePrimary()
}

func (p *Parser) parsePrimary() Expression {
	if p.match("(") {
		expr := p.parseExpression()
		if !p.match(")") {
			panic("缺少右括号")
		}
		return expr
	}

	if p.match("true") {
		return NewConstantExpression(true)
	}

	if p.match("false") {
		return NewConstantExpression(false)
	}

	if p.matchNumber() {
		num, _ := strconv.ParseFloat(p.previous(), 64)
		return NewConstantExpression(num)
	}

	if p.matchString() {
		str := p.previous()
		// 去除引号
		return NewConstantExpression(str[1 : len(str)-1])
	}

	if p.matchFunction() {
		name := p.previous()
		if !p.match("(") {
			panic("函数调用缺少左括号")
		}

		var args []Expression
		if !p.check(")") {
			args = p.parseArguments()
		}

		if !p.match(")") {
			panic("函数调用缺少右括号")
		}

		return NewFunctionCallExpression(name, args)
	}

	// 默认为变量
	token := p.advance()
	return NewVariableExpression(token)
}

func (p *Parser) parseArguments() []Expression {
	args := []Expression{p.parseExpression()}

	for p.match(",") {
		args = append(args, p.parseExpression())
	}

	return args
}

// ========= 解析器辅助方法 =========
func (p *Parser) match(tokens ...string) bool {
	for _, token := range tokens {
		if p.check(token) {
			p.advance()
			return true
		}
	}
	return false
}

func (p *Parser) matchNumber() bool {
	if p.Position >= len(p.Tokens) {
		return false
	}

	_, err := strconv.ParseFloat(p.Tokens[p.Position], 64)
	return err == nil
}

func (p *Parser) matchString() bool {
	if p.Position >= len(p.Tokens) {
		return false
	}

	token := p.Tokens[p.Position]
	return len(token) >= 2 && token[0] == '"' && token[len(token)-1] == '"'
}

func (p *Parser) matchFunction() bool {
	if p.Position >= len(p.Tokens) {
		return false
	}

	// 检查下一个token是否是"("
	if p.Position+1 < len(p.Tokens) && p.Tokens[p.Position+1] == "(" {
		return true
	}

	return false
}

func (p *Parser) check(token string) bool {
	if p.Position >= len(p.Tokens) {
		return false
	}
	return p.Tokens[p.Position] == token
}

func (p *Parser) advance() string {
	if p.Position >= len(p.Tokens) {
		return ""
	}
	token := p.Tokens[p.Position]
	p.Position++
	return token
}

func (p *Parser) previous() string {
	if p.Position == 0 {
		return ""
	}
	return p.Tokens[p.Position-1]
}
